﻿using Microsoft.Graphics.Canvas;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.System.Threading;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Xaml.Shapes;
using 纸片人.AttributeUsageFloder;

// https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板

namespace 纸片人.PageViews
{
    [LastModified("2022-5-12", "create PictureDeform.xaml")]
    [PageType("cpu", "图片变形")]
    /// <summary>
    /// 可用于自身或导航至 Frame 内部的空白页。
    /// </summary>
    public sealed partial class PictureDeform : Page
    {

        double width;
        double height;
        Color[] colors;
        Color[] tempColors;
        WriteableBitmap wb;
        double m;

        public PictureDeform()
        {
            this.InitializeComponent();
        }

        DeformSide tSide, bSide, rSide, lSide;


        private async void selectPicture_Click(object sender, RoutedEventArgs e)
        {
            CanvasBitmap bitmap = await Function.SelectImageAsync();

            if (bitmap == null)
                return;

            int w, h;

            Function.InitialParameter(bitmap, out w, out h, out colors, out tempColors, image, out wb);

            width = w;
            height = h;

            initialRect();
        }


        void initialRect()
        {

            if (width > height)
            {
                m = (double)width / 800d;
                image.Width = 800;
                image.Height = (double)height / m;
            }
            else
            {
                m = (double)height / 500d;
                image.Height = 500;
                image.Width = (double)width / m;
            }

            double cw = canvas.ActualWidth;
            double ch = canvas.ActualHeight;

            int w = (int)image.Width;
            int h = (int)image.Height;

            image.Translation = new System.Numerics.Vector3((float)((cw - w) / 2), (float)((ch - h) / 2), 0);


            Point p = image.TransformToVisual(canvas).TransformPoint(new Point());
            int x = (int)p.X;
            int y = (int)p.Y;

            SetThumbPoint(t0, p);
            SetThumbPoint(t1, new Point(p.X + (image.Width * 0.33), p.Y));
            SetThumbPoint(t2, new Point(p.X + (image.Width * 0.66), p.Y));
            SetThumbPoint(t3, new Point(p.X + (image.Width ), p.Y));

            SetLinePoint(tt1, p, new Point(p.X + (image.Width * 0.33), p.Y));
            SetLinePoint(tt2, new Point(p.X + (image.Width), p.Y), new Point(p.X + image.Width * 0.66,p.Y));


            SetThumbPoint(b0, new Point(p.X,p.Y+image.Height));
            SetThumbPoint(b1, new Point(p.X + (image.Width * 0.33), p.Y + image.Height));
            SetThumbPoint(b2, new Point(p.X + (image.Width * 0.33), p.Y + image.Height));
            SetThumbPoint(b3, new Point(p.X + (image.Width), p.Y + image.Height));

            SetLinePoint(bb1, new Point(x,y+image.Height), new Point(p.X + (image.Width * 0.33), p.Y + image.Height));
            SetLinePoint(bb2, new Point(p.X + (image.Width), p.Y + image.Height), new Point(p.X + image.Width * 0.66, p.Y + image.Height));

            SetThumbPoint(l1, new Point(p.X, p.Y + image.Height* 0.33));
            SetThumbPoint(l2, new Point(p.X , p.Y + image.Height*0.66));

            SetLinePoint(ll1, new Point(x, y), new Point(p.X, p.Y + image.Height* 0.33));
            SetLinePoint(ll2,new Point(x,y+image.Height),new Point(x,y+image.Height*0.66));

            SetThumbPoint(r1, new Point(p.X+image.Width, p.Y + image.Height * 0.33));
            SetThumbPoint(r2, new Point(p.X+image.Width, p.Y + image.Height * 0.66));


            SetLinePoint(rr1, new Point(x + image.Width, y), new Point(p.X + image.Width, p.Y + image.Height * 0.33));
            SetLinePoint(rr2, new Point(x + image.Width, y + image.Height), new Point(x + image.Width, y + image.Height * 0.66));


            tSide = new DeformSide(new Point(0, 0), new Point((width-1) * 0.33, 0), new Point((width-1) * 0.66, 0), new Point((width-1), 0));
            bSide = new DeformSide(new Point(0, (height-1)), new Point((width-1) * 0.33, (height-1)), new Point((width-1) * 0.66, (height-1)), new Point((width-1), (height-1)));


            lSide = new DeformSide(new Point(0,0), new Point(0, (height-1)*0.33), new Point(0, (height-1)*0.66), new Point(0, (height-1)));

            rSide = new DeformSide(new Point((width-1), 0), new Point((width-1), (height-1) * 0.33), new Point((width-1), (height-1) * 0.66), new Point((width-1), (height-1)));


        }


        void SetThumbPoint(Thumb thumb,Point point)
        {
            thumb.Translation = new System.Numerics.Vector3((float)(point.X - 5), (float)(point.Y - 5), 0);
        }

        void SetLinePoint(Line line,Point p0,Point p1)
        {
            line.X1 = p0.X;
            line.Y1 = p0.Y;

            line.X2 = p1.X;
            line.Y2 = p1.Y;
        }




        private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            Thumb thumb = sender as Thumb;

            thumb.Translation = new System.Numerics.Vector3(thumb.Translation.X + (float)e.HorizontalChange, thumb.Translation.Y + (float)e.VerticalChange,0);
            var temp = new Point();
            switch (thumb.Name)
            {
                case "t0":

                    

                    temp.X = (m * e.HorizontalChange) + tSide.P0.X;
                    temp.Y = (m * e.VerticalChange) + tSide.P0.Y;

                    tSide.P0 = temp;
                    lSide.P0 = temp;

                    SetLinePoint(tt1, new Point(t1.Translation.X + 5, t1.Translation.Y + 5), new Point(t0.Translation.X + 5, t0.Translation.Y + 5));

                    SetLinePoint(ll1, new Point(l1.Translation.X + 5, l1.Translation.Y + 5), new Point(t0.Translation.X + 5, t0.Translation.Y + 5));

                    break;

                case "t1":
                    temp.X = (m * e.HorizontalChange) + tSide.P1.X;
                    temp.Y = (m * e.VerticalChange) + tSide.P1.Y;

                    tSide.P1 = temp;
                    SetLinePoint(tt1, new Point(t1.Translation.X + 5, t1.Translation.Y + 5), new Point(t0.Translation.X + 5, t0.Translation.Y + 5));

                    break;

                case "t2":

                    temp.X = (m * e.HorizontalChange) + tSide.P2.X;
                    temp.Y = (m * e.VerticalChange) + tSide.P2.Y;

                    tSide.P2 = temp;
                    SetLinePoint(tt2, new Point(thumb.Translation.X + 5, thumb.Translation.Y + 5), new Point(t3.Translation.X+5,t3.Translation.Y+5) );

                    break;

                case "t3":
                    temp.X = (m * e.HorizontalChange) + tSide.P3.X;
                    temp.Y = (m * e.VerticalChange) + tSide.P3.Y;

                    tSide.P3 = temp;
                    rSide.P0 = temp;

                    SetLinePoint(tt2, new Point(t2.Translation.X + 5, t2.Translation.Y + 5), new Point(t3.Translation.X + 5, t3.Translation.Y + 5));

                    SetLinePoint(rr1, new Point(r1.Translation.X + 5, r1.Translation.Y + 5), new Point(t3.Translation.X + 5, t3.Translation.Y + 5));

                    break;

                case "r1":
                    temp.X = (m * e.HorizontalChange) + rSide.P1.X;
                    temp.Y = (m * e.VerticalChange) + rSide.P1.Y;
                  
                    rSide.P1 = temp;

                   
                    SetLinePoint(rr1, new Point(r1.Translation.X + 5, r1.Translation.Y + 5), new Point(t3.Translation.X + 5, t3.Translation.Y + 5));

                    break;

                case "r2":
                    temp.X = (m * e.HorizontalChange) + rSide.P2.X;
                    temp.Y = (m * e.VerticalChange) + rSide.P2.Y;

                    rSide.P2 = temp;


                    SetLinePoint(rr2, new Point(r2.Translation.X + 5, r2.Translation.Y + 5), new Point(b3.Translation.X + 5, b3.Translation.Y + 5));

                    break;

                case "l1":
                    temp.X = (m * e.HorizontalChange) + lSide.P1.X;
                    temp.Y = (m * e.VerticalChange) + lSide.P1.Y;

                    lSide.P1 = temp;
                    SetLinePoint(ll1, new Point(l1.Translation.X + 5, l1.Translation.Y + 5), new Point(t0.Translation.X + 5,t0.Translation.Y + 5));
                    break;
                case "l2":
                    temp.X = (m * e.HorizontalChange) + lSide.P2.X;
                    temp.Y = (m * e.VerticalChange) + lSide.P2.Y;

                    lSide.P2 = temp;
                    SetLinePoint(ll2, new Point(l2.Translation.X + 5, l2.Translation.Y + 5), new Point(b0.Translation.X + 5,b0.Translation.Y + 5));
                    break;

                case "b0":
                    temp.X = (m * e.HorizontalChange) + bSide.P0.X;
                    temp.Y = (m * e.VerticalChange) + bSide.P0.Y;

                    bSide.P0 = temp;
                    lSide.P3 = temp;
                    SetLinePoint(ll2, new Point(l2.Translation.X + 5, l2.Translation.Y + 5), new Point(b0.Translation.X + 5, b0.Translation.Y + 5));
                    SetLinePoint(bb1, new Point(b1.Translation.X + 5, b1.Translation.Y + 5), new Point(b0.Translation.X + 5, b0.Translation.Y + 5));
                    break;

                case "b1":
                    temp.X = (m * e.HorizontalChange) + bSide.P1.X;
                    temp.Y = (m * e.VerticalChange) + bSide.P1.Y;

                    bSide.P1 = temp;
                    SetLinePoint(bb1, new Point(b1.Translation.X + 5, b1.Translation.Y + 5), new Point(b0.Translation.X + 5, b0.Translation.Y + 5));
                    break;
                case "b2":
                    temp.X = (m * e.HorizontalChange) + bSide.P2.X;
                    temp.Y = (m * e.VerticalChange) + bSide.P2.Y;

                    bSide.P2 = temp;
                    SetLinePoint(bb2, new Point(b2.Translation.X + 5, b2.Translation.Y + 5), new Point(b3.Translation.X + 5, b3.Translation.Y + 5));
                    break;

                case "b3":
                    temp.X = (m * e.HorizontalChange) + bSide.P3.X;
                    temp.Y = (m * e.VerticalChange) + bSide.P3.Y;

                    bSide.P3 = temp;
                    rSide.P3 = temp;
                    SetLinePoint(bb2, new Point(b2.Translation.X + 5, b2.Translation.Y + 5), new Point(b3.Translation.X + 5, b3.Translation.Y + 5));

                    SetLinePoint(rr2, new Point(r2.Translation.X + 5, r2.Translation.Y + 5), new Point(b3.Translation.X + 5, b3.Translation.Y + 5));
                   
                    break;

             


            }





            FreeTrans(1,1);

        }

        private void Thumb_DragCompleted(object sender, DragCompletedEventArgs e)
        {




        }


        void FreeTrans( double imageWidth, double imageHeight)
        {

            Stopwatch sp = new Stopwatch();
 
            double tw = tSide.GetBezierLength();
            double bw = bSide.GetBezierLength();

            double lh = lSide.GetBezierLength();
            double rh = rSide.GetBezierLength();

            double w = Math.Max(tw, bw);
            double h = Math.Max(lh, rh);

            #region 找出四个边的每一个点的位置
            Point[,] matric = new Point[(int)w, (int)h];

            List<IAsyncAction> taskList = new List<IAsyncAction>();

            taskList.Add(ThreadPool.RunAsync(p =>
            {
                for (double x = 0; x < (int)w; x++)
                {
                    double mww = x / (w);


                    //上边点
                    Point txy = tSide.CalculateBezierPointForCubic(mww);
                    //下边点
                    Point bxy = bSide.CalculateBezierPointForCubic(mww);

                    matric[(int)x, 0] = txy;
                    matric[(int)x,(int)(h-1)] = bxy;

                }

        })

            );

            taskList.Add(ThreadPool.RunAsync(p =>
            {
                for (double y = 0; y < (int)h; y++)
                {
                    double mhh = y / (h);

                    //左边边点
                    Point lxy = lSide.CalculateBezierPointForCubic(mhh);
                    //右边点
                    Point rxy = rSide.CalculateBezierPointForCubic(mhh);
                    matric[0, (int)y] = lxy;
                    matric[(int)w-1, (int)y] = rxy;
                }

            })

            );

            Task.WaitAll(taskList.Select(temp => temp.AsTask()).ToArray());

            taskList.Clear();
            #endregion


          

            tempColors = new Color[colors.Length];


         

            Point ltxy = FixPoint(tSide.P0);
            Point rtxy = FixPoint(tSide.P3);



            Point lbxy = FixPoint(bSide.P0);
            Point rbxy = FixPoint(bSide.P3);

           

            Task.WaitAll(PictureFilter.MultiThreading((int)width, (int)height, (sx, sy, ex, ey) =>
            {

                for (double x = sx; x < (int)ex; x++)
                {

                    double mw = x / (width);


                    int mx =(int) (mw * w);

                    //上边点
                    Point txy = FixPoint(matric[(int)mx, 0]);

                    //下边点
                    Point bxy = FixPoint(matric[(int)mx, (int)(h - 1)]);


                    for (double y = sy; y < (int)ey; y++)
                    {

                        double mh = y / (height);

                        double my = mh * h;

                        //左边边点
                        Point lxy = FixPoint(matric[0, (int)my]);
                        //右边点
                        Point rxy = FixPoint(matric[(int)w - 1, (int)my]);



                        double oy = 0, ox = 0;
                        oy = lxy.Y - (lxy.Y - rxy.Y) * mw;
                        ox = txy.X - (txy.X - bxy.X) * mh;

                        double ll = (lxy.X - (ltxy.X - (ltxy.X - lbxy.X) * mh)) * (1 - mw);
                        double rr = (rxy.X - (rtxy.X - (rtxy.X - rbxy.X) * mh)) * mw;
                        ox = ox + ll + rr;

                        double tt = (txy.Y - (ltxy.Y - (ltxy.Y - rtxy.Y) * mw)) * (1 - mh);
                        double dd = (bxy.Y - (lbxy.Y - (lbxy.Y - rbxy.Y) * mw)) * (mh);
                        oy = oy + tt + dd;


                        if (ox < 0 || ox > width - 1 || oy < 0 || oy > height - 1)
                            continue;

                        Color c = colors[(int)x+(int)y*(int)width];

                  
                            tempColors[(int)ox + (int)oy * (int)width] = c;



                        
                            if (lxy.X < 0 || lxy.X > width - 1 || lxy.Y < 0 || lxy.Y > height - 1 || rxy.X < 0 || rxy.X > width - 1 || rxy.Y < 0 || rxy.Y > height - 1)
                                continue;

                            int lIndex = (int)lxy.X + (int)(lxy.Y) * (int)(width);
                            int rIndex = (int)rxy.X + (int)(rxy.Y) * (int)(width);

                            tempColors[lIndex] = Color.FromArgb(255, 0, 0, 0);
                            tempColors[rIndex] = Color.FromArgb(255, 0, 0, 0);
                 

                    }



                 

                        if (txy.X < 0 || txy.X > width - 1 || txy.Y < 0 || txy.Y > height - 1 || bxy.X < 0 || bxy.X > width - 1 || bxy.Y < 0 || bxy.Y > height - 1)
                            continue;
                        int tIndex = (int)txy.X + (int)(txy.Y) * (int)(width);
                        int bIndex = (int)bxy.X + (int)(bxy.Y) * (int)(width);



                    tempColors[tIndex] = Color.FromArgb(255, 0, 0, 0);
                    tempColors[bIndex] = Color.FromArgb(255, 0, 0, 0);
                   


                }

            }, 12).Select(p => p.AsTask()).ToArray());



            tempColors = Function.RencentFillColor(tempColors, width, height);
            tempColors = Function.RencentFillColor(tempColors, width, height);
            tempColors = Function.RencentFillColor(tempColors, width, height);

            Function.InitialImage(tempColors, (int)width, (int)height, image, wb);
        }

        void PartDeform(double sx,double sy,double ex,double ey,Color[] temp,Point[,] matric,double w,double h)
        {
            Point ltxy = FixPoint(tSide.P0);
            Point rtxy = FixPoint(tSide.P3);



            Point lbxy = FixPoint(bSide.P0);
            Point rbxy = FixPoint(bSide.P3);

            for (double x = sx; x < (int)ex; x++)
            {

                double mw = x / (w);

                

                //上边点
                Point txy = FixPoint(matric[(int)x, 0]);

                //下边点
                Point bxy = FixPoint(matric[(int)x, (int)(h - 1)]);


                for (double y = sy; y < (int)ey; y++)
                {

                    double mh = y / (h);

                    //左边边点
                    Point lxy = FixPoint(matric[0, (int)y]);
                    //右边点
                    Point rxy = FixPoint(matric[(int)w - 1, (int)y]);



                    double oy = 0, ox = 0;
                    oy = lxy.Y - (lxy.Y - rxy.Y) * mw;
                    ox = txy.X - (txy.X - bxy.X) * mh;

                    double ll = (lxy.X - (ltxy.X - (ltxy.X - lbxy.X) * mh)) * (1 - mw);
                    double rr = (rxy.X - (rtxy.X - (rtxy.X - rbxy.X) * mh)) * mw;
                    ox = ox + ll + rr;

                    double tt = (txy.Y - (ltxy.Y - (ltxy.Y - rtxy.Y) * mw)) * (1 - mh);
                    double dd = (bxy.Y - (lbxy.Y - (lbxy.Y - rbxy.Y) * mw)) * (mh);
                    oy = oy + tt + dd;


                    if (ox < 0 || ox > width - 1 || oy < 0 || oy > height - 1)
                        continue;

                    Color c = Function.BiLinear(mw * width, mh * height, colors, (int)width, (int)height);

                    try
                    {

                        //tempColors[(int)ox + (int)oy * (int)cw] = colors[(int)(mw * width) + (int)(mh * height) * width];
                        temp[(int)ox + (int)oy * (int)width] = c;

                    }

                    catch
                    {
                        ox = ox > (int)width - 1 ? (int)width - 1 : ox;
                        oy = oy > (int)height - 1 ? (int)height - 1 : oy;
                    }


                    try
                    {
                        if (lxy.X < 0 || lxy.X > width - 1 || lxy.Y < 0 || lxy.Y > height - 1 || rxy.X < 0 || rxy.X > width - 1 || rxy.Y < 0 || rxy.Y > height - 1)
                            continue;

                        int lIndex = (int)lxy.X + (int)(lxy.Y) * (int)(width);
                        int rIndex = (int)rxy.X + (int)(rxy.Y) * (int)(width);

                        temp[lIndex] = Color.FromArgb(255, 0, 0, 0);
                        temp[rIndex] = Color.FromArgb(255, 0, 0, 0);
                    }
                    catch
                    {
                        int lIndex = (int)lxy.X + (int)(lxy.Y) * (int)(w);
                        int rIndex = (int)rxy.X + (int)(rxy.Y) * (int)(w);
                    }

                }



                try
                {

                    if (txy.X < 0 || txy.X > width - 1 || txy.Y < 0 || txy.Y > height - 1 || bxy.X < 0 || bxy.X > width - 1 || bxy.Y < 0 || bxy.Y > height - 1)
                        continue;
                    int tIndex = (int)txy.X + (int)(txy.Y) * (int)(width);
                    int bIndex = (int)bxy.X + (int)(bxy.Y) * (int)(width);



                    temp[tIndex] = Color.FromArgb(255, 0, 0, 0);
                    temp[bIndex] = Color.FromArgb(255, 0, 0, 0);
                }
                catch
                {
                    int tIndex = (int)txy.X + (int)(txy.Y) * (int)(width);
                    int bIndex = (int)bxy.X + (int)(bxy.Y) * (int)(width);
                }



            }

        }


        Point FixPoint(Point point)
        {

            //point = new Point(Math.Round(point.X),Math.Round(point.Y));
            return point;
        }

        private void reset_Click(object sender, RoutedEventArgs e)
        {
            initialRect();
        }

    }

    public class DeformSide
    {

        public Point Left { get; set; } 
        public Point Right { get; set; }
        public Point Top { get; set; }
        public Point Bottom { get; set; }

        public Point P0 { get; set; }
        public Point P1 { get; set; }
        public Point P2 { get; set; }
        public Point P3 { get; set; }

        public DeformSide(Point p0,Point p1,Point p2,Point p3)
        {
            this.P0 = p0;
            this.P1 = p1;

            this.P2 = p2;
            this.P3 = p3;
        }

        public DeformSide(Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3)
        {
            this.P0 = p0.ToPoint();
            this.P1 = p1.ToPoint();

            this.P2 = p2.ToPoint();
            this.P3 = p3.ToPoint();
        }

        public bool InitalPoint = true;


        /// <summary>
        /// 计算贝塞尔每一个点的位置
        /// 
        /// </summary>
        /// <param name="t"></param>
        /// <param name="p0"></param>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="p3"></param>
        /// <returns></returns>
        public Point CalculateBezierPointForCubic(double t)
        {
            var point = new Point();

            var temp = 1 - t;
            point.X = (float)(P0.X * Math.Pow(temp, 3) + 3 *P1.X * t * Math.Pow(temp, 2) + 3 * P2.X * Math.Pow(t, 2) * temp + P3.X * Math.Pow(t, 3));
            point.Y = (float)(P0.Y * Math.Pow(temp, 3) + 3 * P1.Y * t * Math.Pow(temp, 2) + 3 * P2.Y * Math.Pow(t, 2) * temp + P3.Y * Math.Pow(t, 3));
            return point;
        }

        /// <summary>
        /// 计算贝塞尔每一个点的位置
        /// 并找出这条线的上下左右位置
        /// </summary>
        /// <param name="t"></param>
        /// <param name="p0"></param>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="p3"></param>
        /// <returns></returns>
        public Point CalculateBezierPointForCubicAndPoint(double t)
        {
            var point = new Point();

            var temp = 1 - t;
            point.X = (float)(P0.X * Math.Pow(temp, 3) + 3 * P1.X * t * Math.Pow(temp, 2) + 3 * P2.X * Math.Pow(t, 2) * temp + P3.X * Math.Pow(t, 3));
            point.Y = (float)(P0.Y * Math.Pow(temp, 3) + 3 * P1.Y * t * Math.Pow(temp, 2) + 3 * P2.Y * Math.Pow(t, 2) * temp + P3.Y * Math.Pow(t, 3));

            #region

            if (InitalPoint)
            {
                Bottom = Top = Right = Left = point;
                InitalPoint = false;
            }
            
                if (point.X < Left.X)
                {
                    Left = point;
                }

                if (point.X > Right.X)
                {
                    Right = point;
                }
            
         
                if (point.Y < Top.Y)
                {
                    Top = point;
                }
           
         
                if (point.Y > Bottom.Y)
                {
                    Bottom = point;
                }
            

            #endregion
            return point;
        }


        public double GetBezierLength()
        {
            double pointCount = 30;
            double length = 0;
            Point lastPoint = CalculateBezierPointForCubic(0.0 / pointCount);

            for (double i = 1; i <= pointCount; i++)
            {
                Point point = CalculateBezierPointForCubic(i / pointCount);
                length += Math.Sqrt(Math.Pow(point.X - lastPoint.X, 2) + Math.Pow(point.Y - lastPoint.Y, 2));
                lastPoint = point;
            }
            this.BesselLength = length;
            return length;

        }


        public double GetBezierLengthAndPoint()
        {
            double pointCount = 30;
            double length = 0;
            Point lastPoint = CalculateBezierPointForCubicAndPoint(0.0 / pointCount);

            for (double i = 1; i <= pointCount; i++)
            {
                Point point = CalculateBezierPointForCubicAndPoint(i / pointCount);
                length += Math.Sqrt(Math.Pow(point.X - lastPoint.X, 2) + Math.Pow(point.Y - lastPoint.Y, 2));
                lastPoint = point;
            }

            this.BesselLength = length;

            return length;

        }

        public double BesselLength { get; set; }
    }
}
